using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;

[Themeable(true)]
public partial class GridControl : System.Web.UI.UserControl, IPostBackEventHandler
{
	private string _sortExpression = string.Empty;
    private SortDirection _sortDirection = SortDirection.Ascending;
	public event QueryDataSource QueryDataSource;
    public event GridRefresh GridRefresh;
	private bool _allowClientSideSelection = true;
	private string _selectionInfoFormat = string.Empty;
    private string _noSelectionInfoFormat = string.Empty;
    private string _pageInfoFormat = string.Empty;
    private bool _enableViewState = true;
    private List<GridItemID> _itemIds = null;
    private List<GridRowStyle> _rowStyles = null;
    private bool _allowSorting = true;
    private bool _allowPaging = true;
    private bool _highlightSelection = true;

    public string PageInfoFormat
    {
        get 
        {
            if (string.IsNullOrEmpty(_pageInfoFormat))
            {
                _pageInfoFormat = (string)GetLocalResourceObject("PageInfoFormat");
            }
            return _pageInfoFormat;
        }
        set { _pageInfoFormat = value; }
    }

	private string _rowCssClassDataField = string.Empty;

	public string RowCssClassDataField
	{
		get { return _rowCssClassDataField; }
		set { _rowCssClassDataField = value; }
	}
	
	private string _selectedRowCssClassDataField = string.Empty;
	
	public string SelectedRowCssClassDataField
	{
		get { return _selectedRowCssClassDataField; }
		set { _selectedRowCssClassDataField = value; }
	}

    private string _dataIdField = string.Empty;

    public string DataIdField
    {
        get { return _dataIdField; }
        set { _dataIdField = value; }
    }

    private string _dataCodeField = string.Empty;

    public string DataCodeField
    {
        get { return _dataCodeField; }
        set { _dataCodeField = value; }
    }

	private string _dataLabelField = string.Empty;

	public string DataLabelField
	{
		get { return _dataLabelField; }
		set { _dataLabelField = value; }
	}

	private int _pageNumber = 1;
	private bool _hasMorePages;
	private string _pagingCookie = string.Empty;
	public event DataGridItemEventHandler ItemDataBound;
	private bool _hideEmptyHeaderSeperator = false;
	private string _onClientRowDblClick = string.Empty;
	private string _onClientRowSelectionChanged = string.Empty;
	private string _onToggleExpand = string.Empty;
    private bool _allowMultiSelect = true;

    public bool AllowMultiSelect
    {
        get { return _allowMultiSelect; }
        set
        {
            _allowMultiSelect = value;
        }
    }

	private string _cssClass = string.Empty;

	public string CssClass
	{
		get { return _cssClass; }
		set { _cssClass = value; }
	}

	private string _headerCssClass = string.Empty;

	public string HeaderCssClass
	{
		get { return _headerCssClass; }
		set { _headerCssClass = value; }
	}

	private string _headerCellCssClass = string.Empty;

	public string HeaderCellCssClass
	{
		get { return _headerCellCssClass; }
		set { _headerCellCssClass = value; }
	}

	private string _rowCssClass = string.Empty;

	public string RowCssClass
	{
		get { return _rowCssClass; }
		set { _rowCssClass = value; }
	}

	private string _selectedRowCssClass = string.Empty;

	public string SelectedRowCssClass
	{
		get { return _selectedRowCssClass; }
		set { _selectedRowCssClass = value; }
	}

	private string _dataCellCssClass = string.Empty;

	public string DataCellCssClass
	{
		get { return _dataCellCssClass; }
		set { _dataCellCssClass = value; }
	}

	private string _statusBarCssClass = string.Empty;

	public string StatusBarCssClass
	{
		get { return _statusBarCssClass; }
		set { _statusBarCssClass = value; }
	}

	private string _selectionInfoCssClass = string.Empty;

	public string SelectionInfoCssClass
	{
		get { return _selectionInfoCssClass; }
		set { _selectionInfoCssClass = value; }
	}

	private string _pageInfoCssClass = string.Empty;

	public string PageInfoCssClass
	{
		get { return _pageInfoCssClass; }
		set { _pageInfoCssClass = value; }
	}

	public string OnClientRowDblClick
	{
		get { return _onClientRowDblClick; }
		set { _onClientRowDblClick = value; }
	}

	public string OnClientRowSelectionChanged
	{
		get { return _onClientRowSelectionChanged; }
		set
        {
            if (_onClientRowSelectionChanged.IndexOfAny(new char[] { '(', ')', ' ' }) >= 0)
            {
                throw new ArgumentException("Please provide only javascript function identifier");
            }            
            _onClientRowSelectionChanged = value;
        }
	}

	public string OnToggleExpand
	{
		get { return _onToggleExpand; }
		set
        {
            if (_onToggleExpand.IndexOfAny(new char[] { '(', ')', ' ' }) >= 0)
            {
                throw new ArgumentException("Please provide only javascript function identifier");
            }
            _onToggleExpand = value;
        }
	}

	public bool HideEmptyHeaderSeperator
	{
		get { return _hideEmptyHeaderSeperator; }
		set { _hideEmptyHeaderSeperator = value; }
	}

	public string SelectionInfoFormat
	{
		get
        {
            if(string.IsNullOrEmpty(_selectionInfoFormat))
            {
                _selectionInfoFormat = (string)GetLocalResourceObject("SelectionInfoFormat");
            }
            return _selectionInfoFormat;
        }
		set { _selectionInfoFormat = value; }
	}

    public string NoSelectionInfoFormat
    {
        get
        {
            if (string.IsNullOrEmpty(_noSelectionInfoFormat))
            {
                _noSelectionInfoFormat = (string)GetLocalResourceObject("NoSelectionInfoFormat");
            }
            return _noSelectionInfoFormat;
        }
        set { _noSelectionInfoFormat = value; }
    }

	public bool AllowClientSideSelection
	{
		get { return _allowClientSideSelection; }
		set
        {
            _allowClientSideSelection = value;
        }
	}
	
    protected void Page_Load(object sender, EventArgs e)
    {
        if (this.innerGrid.EnableViewState != this.EnableViewState)
        {
            this.innerGrid.EnableViewState = this.EnableViewState;
        }

		if (this.ViewState["SortExpression"] != null)
        {
            this._sortExpression = (string)this.ViewState["SortExpression"];
        }

        if (this.ViewState["SortDirection"] != null)
        {
            this._sortDirection = (SortDirection)this.ViewState["SortDirection"];
        }

		if (this.ViewState["PageNumber"] != null)
		{
			this._pageNumber = (int)this.ViewState["PageNumber"];
		}

		if (this.ViewState["HasMorePages"] != null)
		{
			this._hasMorePages = (bool)this.ViewState["HasMorePages"];
		}

        if (this.ViewState["AllowMultiSelect"] != null)
        {
            this._allowMultiSelect = (bool)this.ViewState["AllowMultiSelect"];
        }

        if (this.ViewState["AllowClientSideSelection"] != null)
        {
            this._allowClientSideSelection = (bool)this.ViewState["AllowClientSideSelection"];
        }
		
		this.lblPageInfo.Text = string.Format(this.PageInfoFormat, this._pageNumber);
		
		if (this.ViewState["PagingCookie"] != null)
		{
			this._pagingCookie = (string)this.ViewState["PagingCookie"];
		}

        if (this.ViewState["ItemIds"] != null)
        {
            this._itemIds = new List<GridItemID>();
            GridItemID[] itemIds = (GridItemID[])this.ViewState["ItemIds"];
            this._itemIds.AddRange(itemIds);
        }

		if (this.ViewState["RowStyles"] != null)
		{
			this._rowStyles = new List<GridRowStyle>();
			GridRowStyle[] rowStyles = (GridRowStyle[])this.ViewState["RowStyles"];
			this._rowStyles.AddRange(rowStyles);
		}

		if (this.ViewState["AllowSorting"] != null)
		{
			this._allowSorting = (bool)this.ViewState["AllowSorting"];
		}

		if (this.ViewState["AllowPaging"] != null)
		{
			this._allowPaging = (bool)this.ViewState["AllowPaging"];
		}

		if (this.ViewState["HighlightSelection"] != null)
		{
			this._highlightSelection = (bool)this.ViewState["HighlightSelection"];
		}

        if (this.ViewState["SelectionInfoFormat"] != null)
        {
            this.ViewState["SelectionInfoFormat"] = this.SelectionInfoFormat;
        }

        if (this.ViewState["NoSelectionInfoFormat"] != null)
        {
            this.ViewState["NoSelectionInfoFormat"] = this.NoSelectionInfoFormat;
        }

        BoundColumn lastColumn = new BoundColumn();
        lastColumn.SortExpression = "!";
        lastColumn.HeaderStyle.Width = new Unit("100%");
        lastColumn.ItemStyle.Width = new Unit("100%");
        this.innerGrid.Columns.Add(lastColumn);

        if (!IsPostBack || this.EnableViewState == false)
        {
			DoQueryDataSource(QueryDataSourceReason.DataBind);
        }

        RegisterScripts();
    }

	public void Rebind()
	{
		DoQueryDataSource(QueryDataSourceReason.DataBind);
	}

    private void RegisterScripts()
    {
        Type thisType = this.GetType();

		String scriptName = "common.js";
		String scriptUrl = ResolveUrl("ControlScripts/common.js");

		if (!Page.ClientScript.IsClientScriptIncludeRegistered(typeof(Page), scriptName))
		{
			Page.ClientScript.RegisterClientScriptInclude(typeof(Page), scriptName, ResolveClientUrl(scriptUrl));
		}

		scriptName = "GridControl.js";
        scriptUrl = ResolveUrl("ControlScripts/GridControl.js");
        
        if (!Page.ClientScript.IsClientScriptIncludeRegistered(thisType, scriptName))
        {
            Page.ClientScript.RegisterClientScriptInclude(thisType, scriptName, ResolveClientUrl(scriptUrl));
        }

		string initFunction = this.ClientID + "_Init";
        string resizeFunction = this.ClientID + "_Resize";
        string declareGridControl = "var oGridControl = document.getElementById('" + this.ClientID + "');";
        string attachGridControl = "document." + this.ID + " = oGridControl;";
		string resizeColumnsCall = "GridControl_ResizeColumns(oGridControl);";
		string handleScrollCall = "GridControl_HandleScroll(oGridControl);";
		string resizeHandler = "function " + resizeFunction + "(){" + declareGridControl + resizeColumnsCall + "}";
        string attachGridControlHeaderTable = "oGridControl.gridHeader = document.getElementById('" + this.headerTable.ClientID + "');";
        string attachGridControlInnerGrid = "oGridControl.innerGrid = document.getElementById('" + this.innerGrid.ClientID + "');";
        string attachGridControlGridArea = "oGridControl.gridArea = document.getElementById('" + this.pnlGridArea.ClientID + "');";
        string attachGridControlHeaderArea = "oGridControl.headerArea = document.getElementById('" + this.pnlHeader.ClientID + "');";
        string attachGridControlSelectionInfoArea = "oGridControl.selectionInfoArea = document.getElementById('" + this.pnlSelectInfo.ClientID + "');";
        string attachGridControlSelectedIndices = "oGridControl.selectedIndices = document.getElementById('" + this.hdnSelectedIndices.ClientID + "');";
		string attachGridControlItemsExpanded = "oGridControl.itemsExpanded = document.getElementById('" + this.hdnItemsExpanded.ClientID + "');";
		string attachGridControlStyleArray = "oGridControl.styleArray = document.getElementById('" + this.hdnControlStyles.ClientID + "').value.split(',');";
        string attachGridControl_GetSelectedItems = "oGridControl.getSelectedItems = GridControl_GetSelectedItems;";
		string attachGridControl_GetItem = "oGridControl.getItem = GridControl_GetItem;";
		string attachGridControl_GetItemCount = "oGridControl.getItemCount = GridControl_GetItemCount;";
		string attachGridControl_SelectRow = "oGridControl.selectRow = " + (this.AllowMultiSelect ? "GridControl_SelectRow;" : "GridControl_SingleSelectRow;");
        string attachGridControl_SelectAll = "oGridControl.selectAll = " + (this.AllowMultiSelect ? "GridControl_SelectAll;" : "function(){ throw JsMsg_GridControl_SelectAllNotSupported; };");
        string attachGridControl_Refresh = "oGridControl.refresh = function(){" + this.Page.ClientScript.GetPostBackEventReference(this, "gridcontrol_refresh") + "};";
        string attachGridControl_ToggleExpandColumn = "oGridControl.toggleExpandColumn = GridControl_ToggleExpandColumn;";
        string attachGridControl_IsColumnExpanded = "oGridControl.isColumnExpanded = GridControl_IsColumnExpanded;";
		string attachGridControl_ToggleExpand = "oGridControl.toggleExpand = " + (string.IsNullOrEmpty(this.OnToggleExpand)? "null;" : this.OnToggleExpand + ";");
		string attachGridControl_ClientRowSelectionChanged = "oGridControl.onClientRowSelectionChanged = " + (string.IsNullOrEmpty(this.OnClientRowSelectionChanged) ? "null;" : this.OnClientRowSelectionChanged + ";");
		string attachAllowClientSideSelection = "oGridControl.allowClientSideSelection = " + (this.AllowClientSideSelection ? "true" : "false") + ";";
		string attachAllowSorting = "oGridControl.allowSorting = " + (this.AllowSorting ? "true" : "false") + ";";
        string attachSelectionInfoFormat = "oGridControl.selectionInfoFormat = '" + this.SelectionInfoFormat + "';";
        string attachNoSelectionInfoFormat = "oGridControl.noSelectionInfoFormat = '" + this.NoSelectionInfoFormat + "';";
        string initHandler = "function " + initFunction + "(){ " + declareGridControl + attachGridControl + attachGridControlHeaderTable + attachGridControlInnerGrid + attachGridControlGridArea + attachGridControlHeaderArea + attachGridControlSelectionInfoArea + attachGridControlSelectedIndices + attachGridControlItemsExpanded + attachGridControlStyleArray + attachAllowClientSideSelection + attachAllowSorting + resizeColumnsCall + handleScrollCall + attachGridControl_SelectRow + attachGridControl_SelectAll + attachGridControl_ToggleExpandColumn + attachGridControl_IsColumnExpanded + attachGridControl_ToggleExpand + attachGridControl_ClientRowSelectionChanged + attachGridControl_GetSelectedItems + attachGridControl_GetItem + attachGridControl_GetItemCount + attachGridControl_Refresh + attachSelectionInfoFormat + attachNoSelectionInfoFormat + "}";
        string initCall = initFunction + "();";
        string attachInitHandler = "attachEndRequestHandler( " + initFunction + ");";
        string attachResizeHandler = "window.attachEvent('onresize', " + resizeFunction + ");";
        string script = initHandler + resizeHandler + attachInitHandler + attachResizeHandler + initCall;
        Page.ClientScript.RegisterStartupScript(this.GetType(), Guid.NewGuid().ToString(), script, true);

        //Js Messages
        string jsMsg_GridControl_ClientSideSelectionNotEnabled = "var JsMsg_GridControl_ClientSideSelectionNotEnabled = \"" + GetLocalResourceObject("JsMsg_GridControl_ClientSideSelectionNotEnabled") + "\";";
        string jsMsg_GridControl_SelectAllNotSupported = "var JsMsg_GridControl_SelectAllNotSupported = \"" + GetLocalResourceObject("JsMsg_GridControl_SelectAllNotSupported") + "\";";
        string jsMessages = jsMsg_GridControl_ClientSideSelectionNotEnabled + jsMsg_GridControl_SelectAllNotSupported;
        Page.ClientScript.RegisterStartupScript(this.GetType(), this.GetType().FullName, jsMessages, true);

    }
    
	public int[] SelectedIndices
	{
		get
		{
			string[] selectedItems = hdnSelectedIndices.Value.Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries);
			int[] selectedIndices = new int[selectedItems.Length];
			for(int I = 0; I < selectedItems.Length; I++)
			{
				selectedIndices[I] = int.Parse(selectedItems[I]);
			}
			return selectedIndices;
		}
		set
		{
			string selections = string.Empty;
			if(value != null)
			foreach (int I in value)
			{
				if(!string.IsNullOrEmpty(selections))
				{
					selections += ",";
				}
				selections += I.ToString();
			}
			hdnSelectedIndices.Value = selections;
		}
	}
	
    private void DoQueryDataSource(QueryDataSourceReason reason)
    {
        //PagingInfo pageInfo = new PagingInfo();
        //pageInfo.Count = 50;
        //pageInfo.PageNumber = 1; 


        if(this.QueryDataSource != null)
	    {
            QueryDataSourceEventArgs args = new QueryDataSourceEventArgs();
            args.PageNumber = this._pageNumber;
            args.PagingCookie = this._pagingCookie;
            args.SortDirection = this._sortDirection;
            args.SortExpression = this._sortExpression;
            args.Reason = reason;
            if (reason != QueryDataSourceReason.DataBind)
            {
                args.ClearSelections = true;
            }
		    this.QueryDataSource(this, args);
            if (this._sortExpression != args.SortExpression)
            {
                this._sortExpression = args.SortExpression;
                this.ViewState["SortExpression"] = _sortExpression;
            }
            if (this._sortDirection != args.SortDirection)
            {
                this._sortDirection = args.SortDirection;
                this.ViewState["SortDirection"] = _sortDirection;
			}
			if (this._sortDirection != args.SortDirection)
			{
				this._sortDirection = args.SortDirection;
				this.ViewState["SortDirection"] = _sortDirection;
			}
			if (this._pageNumber != args.PageNumber)
			{
				this._pageNumber = args.PageNumber;
				this.ViewState["PageNumber"] = _pageNumber;
			}
			if (this._hasMorePages != args.HasMorePages)
			{
				this._hasMorePages = args.HasMorePages;
				this.ViewState["HasMorePages"] = _hasMorePages;
			}
			if (this._pagingCookie != args.PagingCookie)
			{
				this._pagingCookie = args.PagingCookie;
				this._pagingCookie = (string)this.ViewState["PagingCookie"];
			}

            if (args.ClearSelections)
            {
                this.SelectedIndices = null;
            }
	    }
    }

    [MergableProperty(false), PersistenceMode(PersistenceMode.InnerDefaultProperty)]
	public DataGridColumnCollection Columns
	{
		get
		{
			return this.innerGrid.Columns;
		}
	}

    public DataGridItemCollection Items
    {
        get
        {
            return this.innerGrid.Items;
        }
    }

    public override bool EnableViewState
    {
		get
		{
            return this._enableViewState;
		}
		set
		{
            this._enableViewState = value;
            if (this.innerGrid != null)
            {
                this.innerGrid.EnableViewState = value;
            }
		}
    }
    
    public bool AllowSorting
    {
		get
		{
            return this._allowSorting;
		}
		set
		{
            this._allowSorting = value;
		}
    }

	public bool AllowPaging
	{
		get
		{
			return this._allowPaging;
		}
		set
		{
			this._allowPaging = value;
		}
	}

	public bool HighlightSelection
	{
		get
		{
			return this._highlightSelection;
		}
		set
		{
			this._highlightSelection = value;
		}
	}

    public object DataSource
    {
		get
		{
			return this.innerGrid.DataSource;
		}
		set
		{
			this.innerGrid.DataSource = value;
            if (this._itemIds != null)
            {
                this._itemIds.Clear();
                this._itemIds = null;
				this.ViewState.Remove("ItemIds");
            }
			if (this._rowStyles != null)
			{
				this._rowStyles.Clear();
				this._rowStyles = null;
				this.ViewState.Remove("RowStyles");
			}
		}
    }
    
    public bool DisplayStatusBar
    {
		get
		{
			return statusBarRow.Visible;
		}
		set
		{
			statusBarRow.Visible = value;
		}
    }
    
    public bool AutoGenerateColumns
    {
		get
		{
			return innerGrid.AutoGenerateColumns;
		}
		set
		{
			innerGrid.AutoGenerateColumns = value;
		}
    }

    private string _firstPageImageUrl = string.Empty;

    public string FirstPageImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._firstPageImageUrl))
            {
                _firstPageImageUrl = ResolveUrl("ControlImages/gc_firstpage.gif");
            }
            return _firstPageImageUrl;
        }
        set
        {
            _firstPageImageUrl = value;
        }
    }

    private string _firstPageDisabledImageUrl = string.Empty;

    public string FirstPageDisabledImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._firstPageDisabledImageUrl))
            {
                _firstPageImageUrl = ResolveUrl("ControlImages/gc_firstpaged.gif");
            }
            return _firstPageImageUrl;
        }
        set
        {
            _firstPageImageUrl = value;
        }
    }

    private string _nextPageImageUrl = string.Empty;

    public string NextPageImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._nextPageImageUrl))
            {
                _nextPageImageUrl = ResolveUrl("ControlImages/gc_nextpage.gif");
            }
            return _nextPageImageUrl;
        }
        set
        {
            _nextPageImageUrl = value;
        }
    }

    private string _nextPageDisabledImageUrl = string.Empty;

    public string NextPageDisabledImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._nextPageDisabledImageUrl))
            {
                _nextPageDisabledImageUrl = ResolveUrl("ControlImages/gc_nextpaged.gif");
            }
            return _nextPageDisabledImageUrl;
        }
        set
        {
            _nextPageDisabledImageUrl = value;
        }
    }

    private string _prevPageImageUrl = string.Empty;

    public string PrevPageImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._prevPageImageUrl))
            {
                _prevPageImageUrl = ResolveUrl("ControlImages/gc_prevpage.gif");
            }
            return _prevPageImageUrl;
        }
        set
        {
            _prevPageImageUrl = value;
        }
    }

    private string _prevPageDisabledImageUrl = string.Empty;

    public string PrevPageDisabledImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._prevPageDisabledImageUrl))
            {
                _prevPageDisabledImageUrl = ResolveUrl("ControlImages/gc_prevpaged.gif");
            }
            return _prevPageDisabledImageUrl;
        }
        set
        {
            _prevPageDisabledImageUrl = value;
        }
    }

    private string _headerSeparatorImageUrl = string.Empty;

    public string HeaderSeparatorImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._headerSeparatorImageUrl))
            {
                _headerSeparatorImageUrl = ResolveUrl("ControlImages/gc_separator.gif");
            }
            return _headerSeparatorImageUrl;
        }
        set
        {
            _headerSeparatorImageUrl = value;
        }
    }

    private string _sortAscendingImageUrl = string.Empty;

    public string SortAscendingImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._sortAscendingImageUrl))
            {
                _sortAscendingImageUrl = ResolveUrl("ControlImages/gc_sortasc.gif");
            }
            return _sortAscendingImageUrl;
        }
        set
        {
            _sortAscendingImageUrl = value;
        }
    }

    private string _sortDescendingImageUrl = string.Empty;

    public string SortDescendingImageUrl
    {
        get
        {
            if (string.IsNullOrEmpty(this._sortDescendingImageUrl))
            {
                _sortDescendingImageUrl = ResolveUrl("ControlImages/gc_sortdesc.gif");
            }
            return _sortDescendingImageUrl;
        }
        set
        {
            _sortDescendingImageUrl = value;
        }
    }

    public override string ClientID
    {
        get
        {
            return crmGrid.ClientID;
        }
    }

    public override void DataBind()
    {
		this.innerGrid.DataBind();
    }

	private void SaveControlStyles()
	{
		this.hdnControlStyles.Value =	this.CssClass + "," +
										this.HeaderCssClass + "," +
										this.HeaderCellCssClass + "," +
										this.RowCssClass + "," +
										this.SelectedRowCssClass + "," +
										this.DataCellCssClass + "," +
										this.StatusBarCssClass + "," +
										this.SelectionInfoCssClass + "," +
										this.PageInfoCssClass;
	}
	
    protected override void OnPreRender(EventArgs e)
    {
        this.ViewState["AllowMultiSelect"] = this._allowMultiSelect;
        this.ViewState["AllowClientSideSelection"] = this._allowClientSideSelection;
        this.ViewState["AllowSorting"] = this._allowSorting;
		this.ViewState["AllowPaging"] = this._allowPaging;
		this.ViewState["HighlightSelection"] = this._highlightSelection;
        this.ViewState["SelectionInfoFormat"] = this.SelectionInfoFormat;
        this.ViewState["NoSelectionInfoFormat"] = this.NoSelectionInfoFormat;
        
        if (this._itemIds != null)
        {
            this.ViewState["ItemIds"] = this._itemIds.ToArray();
        }

		if (this._rowStyles != null)
		{
			this.ViewState["RowStyles"] = this._rowStyles.ToArray();
		}

        base.OnPreRender(e);
        
        SaveControlStyles();
        
        this.crmGrid.CssClass = this.CssClass;
		this.pnlHeader.CssClass = this.HeaderCssClass;
        this.headerTable.CssClass = this.HeaderCssClass;
        this.innerGrid.SelectedItemStyle.CssClass = this.SelectedRowCssClass;
		this.statusBarRow.CssClass = this.StatusBarCssClass;
		this.statusTable.CssClass = this.StatusBarCssClass;
		this.pageInfo.Visible = this.AllowPaging;
        this.pageInfo.CssClass = this.PageInfoCssClass;
        this.selectionInfo.CssClass = this.SelectionInfoCssClass;

		if (this._hasMorePages)
		{
			this.nextPage.Enabled = true;
			this.nextPage.ImageUrl = this.NextPageImageUrl;
		}
		else
		{
			this.nextPage.Enabled = false;
			this.nextPage.ImageUrl = this.NextPageDisabledImageUrl;
		}

		if (this._pageNumber > 1)
		{
			this.firstPage.Enabled = true;
			this.firstPage.ImageUrl = this.FirstPageImageUrl;
			this.prevPage.Enabled = true;
			this.prevPage.ImageUrl = this.PrevPageImageUrl;
		}
		else
		{
			this.firstPage.Enabled = false;
			this.firstPage.ImageUrl = this.FirstPageDisabledImageUrl;
			this.prevPage.Enabled = false;
			this.prevPage.ImageUrl = this.PrevPageDisabledImageUrl;
		}

		int[] SelectedIndices = this.SelectedIndices;
        
        this.Columns[0].Visible = this.AllowClientSideSelection;		
		
        if (innerGrid.DataSource == null)
        {
            string[] cols = this.ViewState["columnTexts"] as string[];
            if (cols != null)
            {
                TableRow row = new TableRow();
                this.headerTable.Rows.Add(row);
                for (int I = 0; I < cols.Length; I++)
                {
                    TableCell headerCell = new TableCell();
                    headerCell.Text = cols[I];
					headerCell.CssClass = this.HeaderCellCssClass;
                    row.Cells.Add(headerCell);
                }
            }
            return;
        }
		
		DataGrid grid = this.innerGrid;

		Table gridTable = grid.Controls[0] as Table;
		
		if(gridTable.Rows.Count > 0)
		{
			gridTable.Rows[0].CssClass = this.HeaderCssClass;
			for(int cell = 0; cell < gridTable.Rows[0].Cells.Count; cell++)
			{
				TableCell hdrcell = gridTable.Rows[0].Cells[cell];
                hdrcell.Attributes.Add("nowrap", "nowrap");
				hdrcell.CssClass = this.HeaderCellCssClass;
				hdrcell.Wrap = false;
			}			
		}

        TableRow headerRow = new TableRow();
		headerTable.Rows.Clear();
		headerTable.Rows.Add(headerRow);
		
		int iLastIndex = gridTable.Rows[0].Cells.Count - 1;

        string sortIndicator = string.Empty;

		if(this.AllowSorting)
		{
			if (this._sortDirection == SortDirection.Ascending)
			{
				sortIndicator = "<img src='" + this.SortAscendingImageUrl + "' align='middle'>";
			}
			else
			{
				sortIndicator = "<img src='" + this.SortDescendingImageUrl + "' align='middle'>";
			}
        }
		
		int iSortIndex = -1;
		string selectAllTag = string.Empty;
		
		if(grid.Items.Count == 0 || AllowMultiSelect == false)
		{
			selectAllTag = string.Empty;
		}
		else if(SelectedIndices.Length == grid.Items.Count)
		{
            selectAllTag = "<input id='chkSelectAll' type='checkbox' style='border:none;display:inline' valign='top' onclick=\"document.getElementById('" + this.ClientID + "').selectAll(this.checked)\" Checked='checked'/>";
		}
		else
		{
            selectAllTag = "<input id='chkSelectAll' type='checkbox' style='border:none;display:inline' valign='top' onclick=\"document.getElementById('" + this.ClientID + "').selectAll(this.checked)\"/>";			
		}
		
		for(int I = (AllowClientSideSelection ? 0 : 1); I <= iLastIndex ; I++)
		{
			TableCell headerCell = new TableCell();

            if (this.Columns.Count > I)
            {
                if (innerGrid.Columns[I].SortExpression == _sortExpression)
                {
                    iSortIndex = I;
                }
            }
            else
            {
				int iIndex = I - this.Columns.Count;
				
                if (innerGrid.DataSource is DataTable)
                {
                    DataTable dt = innerGrid.DataSource as DataTable;
                    if (dt.Columns[iIndex].ColumnName == _sortExpression)
                    {
						iSortIndex = I;
                    }
                }
                else if (innerGrid.DataSource is DataView)
                {
                    DataView dv = innerGrid.DataSource as DataView;
                    if (dv.Table.Columns[iIndex].ColumnName == _sortExpression)
                    {
						iSortIndex = I;
                    }
                }
            }
            
			string cellContent = (I > 0 ? "{0}" : selectAllTag);
            
            HtmlGenericControl span = new HtmlGenericControl();
            span.TagName = "span";
            span.InnerHtml = (I == iSortIndex ? sortIndicator : string.Empty);
            gridTable.Rows[0].Cells[I].Controls.Add(span);

            foreach(Control control in gridTable.Rows[0].Cells[I].Controls)
            {
                if (control is WebControl)
                {
                    ((WebControl)control).CssClass = this.HeaderCellCssClass;
                }
                else if(control is HtmlControl)
                {
                    ((HtmlControl)control).Attributes.Add("class", this.HeaderCellCssClass);
                }
            }

            if (I < iLastIndex && (I > 0 || AllowClientSideSelection == false))
            {
				if (HideEmptyHeaderSeperator == false || innerGrid.Columns.Count <= I || string.IsNullOrEmpty(innerGrid.Columns[I].HeaderText) == false)
				{
                    HtmlImage image = new HtmlImage();
                    image.Src = this.HeaderSeparatorImageUrl;
                    image.Attributes.Add("align", "right");
                    image.Attributes.Add("hspace", "4px");
                    image.Attributes.Add("width", "2px");
                    image.Attributes.Add("height", "14px");
                    gridTable.Rows[0].Cells[I].Controls.AddAt(0, image);
				}
            }
            
			headerCell.Text = cellContent;
			headerCell.Wrap = false;
			headerCell.CssClass = this.HeaderCellCssClass;
            headerCell.Attributes.Add("ondblclick", "document.getElementById('" + this.ClientID + "').toggleExpandColumn(this.cellIndex);");
			gridTable.Rows[0].Cells[I].CssClass = this.HeaderCellCssClass;
            headerRow.Cells.Add(headerCell);
		}
		
        if (SelectedIndices.Length == 0)
        {
            lblSelectionInfo.Text = string.Format(this.NoSelectionInfoFormat, innerGrid.Items.Count.ToString());
        }
        else
        {
            lblSelectionInfo.Text = string.Format(this.SelectionInfoFormat, innerGrid.Items.Count.ToString(), SelectedIndices.Length);
        }
		
		foreach(int index in SelectedIndices)
		{
			int selIndex = index + 1;
			if(this.AllowClientSideSelection)
			{
                HtmlInputControl chkSelectRow = (HtmlInputControl)innerGrid.Items[index].Cells[0].FindControl("chkSelectRow");
                if (chkSelectRow != null)
                {
                    chkSelectRow.Attributes.Add("Checked", "checked");
                }
			}

			string selectedRowCssClass = this.SelectedRowCssClass;
			
			if (this._rowStyles != null && this._rowStyles.Count >= selIndex)
			{
				GridRowStyle rowStyle = this._rowStyles[index];
				if (rowStyle != null)
				{
					if (!string.IsNullOrEmpty(rowStyle.SelectedRowCssClass))
					{
						selectedRowCssClass = rowStyle.SelectedRowCssClass;
					}
				}
			}
			
			gridTable.Rows[selIndex].CssClass = selectedRowCssClass;
		}

		for (int rowIndex = 1; rowIndex <= innerGrid.Items.Count; rowIndex++)
		{
			TableRow row = gridTable.Rows[rowIndex];
			bool IsSelected = gridTable.Rows[rowIndex].CssClass == this.SelectedRowCssClass;
			if(!IsSelected)
			row.CssClass = this.RowCssClass;

            string doSingleSelect = "GridControl_HandleDblClick(document.getElementById('" + this.ClientID + "'))";
            string DblClickHandler = doSingleSelect;
            if (!string.IsNullOrEmpty(OnClientRowDblClick)) {
	            DblClickHandler = OnClientRowDblClick+"("+doSingleSelect+")";
	        }

            if (this._itemIds != null && _itemIds.Count >= rowIndex)
            {
                GridItemID id = this._itemIds[rowIndex - 1];
                if (id != null)
                {
                    if (id.ID != null)
                    {
                        row.Attributes.Add("itemid", id.ID.ToString());
                    }
                    if (id.Code != null)
                    {
                        row.Attributes.Add("itemcode", id.Code.ToString());
                    }
                    if(id.Label != null)
                    {
						row.Attributes.Add("itemlabel", id.Label.ToString());
                    }
                }
            }

			if (this._rowStyles != null && this._rowStyles.Count >= rowIndex)
			{
				GridRowStyle rowStyle = this._rowStyles[rowIndex - 1];
				if (rowStyle != null)
				{
					if(!string.IsNullOrEmpty(rowStyle.RowCssClass))
					{
						row.Attributes.Add("rowCssClass", rowStyle.RowCssClass);
						row.CssClass = rowStyle.RowCssClass;
					}

					if (!string.IsNullOrEmpty(rowStyle.SelectedRowCssClass))
					{
						row.Attributes.Add("selectedRowCssClass", rowStyle.SelectedRowCssClass);
					}
				}
			}

            row.Attributes.Add("ondblclick", DblClickHandler);
			for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
			{
				TableCell cell = row.Cells[cellIndex];
				cell.Wrap = false;
                cell.CssClass = this.DataCellCssClass;
			}

            HtmlInputControl chkSelectRow = (HtmlInputControl)innerGrid.Items[rowIndex - 1].Cells[0].FindControl("chkSelectRow");
            if (chkSelectRow != null)
            {
                chkSelectRow.Attributes.Add("onclick", "document.getElementById('" + this.ClientID + "').selectRow(this.parentElement.parentElement.rowIndex, this.checked)");
            }
		}

        this.pnlGridArea.Attributes.Add("onscroll", "GridControl_HandleScroll(document.getElementById('" + this.ClientID + "'))");

		if (this.innerGrid.EnableViewState)
		{
			string[] headerCols = new string[headerRow.Cells.Count];
			for (int I = 0; I < headerRow.Cells.Count; I++)
			{
				headerCols[I] = headerRow.Cells[I].Text;
			}
			this.ViewState["columnTexts"] = headerCols;
		}
    }

    protected void gridInner_SortCommand(object source, DataGridSortCommandEventArgs e)
    {
        if (this._sortExpression == e.SortExpression)
        {
            if (this._sortDirection == SortDirection.Ascending)
            {
                this._sortDirection = SortDirection.Descending;
            }
            else
            {
                this._sortDirection = SortDirection.Ascending;
            }
        }
        else
        {
            this._sortExpression = e.SortExpression;
            this._sortDirection = SortDirection.Ascending;
        }
        
        this._pagingCookie = "";

        DoQueryDataSource(QueryDataSourceReason.SortCommand);

        this.ViewState["SortExpression"] = _sortExpression;
        this.ViewState["SortDirection"] = _sortDirection;
		this.ViewState["PagingCookie"] = _pagingCookie;
    }

    protected void gridInner_ItemDataBound(object sender, DataGridItemEventArgs e)
    {
        if (this.ItemDataBound != null)
        {
            this.ItemDataBound(sender, e);
        }
    }

    protected void gridInner_ItemCreated(object sender, DataGridItemEventArgs e)
    {
        if (this.ItemDataBound != null)
        {
            this.ItemDataBound(sender, e);
        }
        if (e.Item.ItemType == ListItemType.Header)
        {
            for(int I = 1; I < innerGrid.Columns.Count ; I++)
		    {
                innerGrid.Columns[I].ItemStyle.Width = Unit.Empty;
                TableCell cell = e.Item.Cells[I];
                cell.Wrap = false;
                //if (innerGrid.Columns[I].HeaderStyle.Width.IsEmpty)
                //{
                    //cell.Style.Add(HtmlTextWriterStyle.PaddingRight, "32px");
                //}
                //if (I == 0)
                //{
                //    HtmlImage image = new HtmlImage();
                //    image.Src = "~/Images/ico_16_2_d.gif";
                //    cell.Controls.Add(image);
                //}
            }
        }
        else if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.SelectedItem)
        {
            if (e.Item.DataItem != null && (!string.IsNullOrEmpty(this.DataIdField) || !string.IsNullOrEmpty(this.DataCodeField) || !string.IsNullOrEmpty(this.DataLabelField)))
            {
                GridItemID itemID = null;
                if (e.Item.DataItem is DataRowView)
                {
                    DataRowView view = (DataRowView)e.Item.DataItem;
                    if (!string.IsNullOrEmpty(this.DataIdField))
                    {
                        itemID = new GridItemID();
                        itemID.ID = view.Row[this.DataIdField];
                    }
                    if (!string.IsNullOrEmpty(this.DataCodeField))
                    {
                        if (itemID == null)
                        {
                            itemID = new GridItemID();
                        }
                        itemID.Code = view.Row[this.DataCodeField];
                    }
					if (!string.IsNullOrEmpty(this.DataLabelField))
					{
						if (itemID == null)
						{
							itemID = new GridItemID();
						}
						itemID.Label = view.Row[this.DataLabelField];
					}
                }
                else
                {
                    Type type = e.Item.DataItem.GetType();
                    if (!string.IsNullOrEmpty(this.DataIdField))
                    {
                        PropertyInfo pi = type.GetProperty(this.DataIdField, BindingFlags.Public | BindingFlags.Instance);
                        if (pi != null)
                        {
                            itemID = new GridItemID();
                            itemID.ID = pi.GetValue(e.Item.DataItem, null);                        
                        }
                    }
                    if (!string.IsNullOrEmpty(this.DataCodeField))
                    {
                        PropertyInfo pi = type.GetProperty(this.DataCodeField, BindingFlags.Public | BindingFlags.Instance);
                        if (pi != null)
                        {
                            if (itemID == null)
                            {
                                itemID = new GridItemID();
                            }
                            itemID.Code = pi.GetValue(e.Item.DataItem, null);
                        }
					}
					if (!string.IsNullOrEmpty(this.DataLabelField))
					{
						PropertyInfo pi = type.GetProperty(this.DataLabelField, BindingFlags.Public | BindingFlags.Instance);
						if (pi != null)
						{
							if (itemID == null)
							{
								itemID = new GridItemID();
							}
							itemID.Label = pi.GetValue(e.Item.DataItem, null);
						}
					}
                }
                if (itemID != null)
                {
                    if (this._itemIds == null)
                    {
                        this._itemIds = new List<GridItemID>();
                    }
                    this._itemIds.Insert(e.Item.DataSetIndex, itemID);
                }
            }
            
            if (e.Item.DataItem != null && (!string.IsNullOrEmpty(this.SelectedRowCssClassDataField) || !string.IsNullOrEmpty(this.RowCssClassDataField)))
            {
				GridRowStyle rowStyle = null;
				if (e.Item.DataItem is DataRowView)
				{
					DataRowView view = (DataRowView)e.Item.DataItem;
					if (!string.IsNullOrEmpty(this.RowCssClassDataField))
					{
						rowStyle = new GridRowStyle();
						object value = view.Row[this.RowCssClassDataField];
						if(value != null)
						{
							rowStyle.RowCssClass = value.ToString();
						}
					}
					if (!string.IsNullOrEmpty(this.SelectedRowCssClassDataField))
					{
						if (rowStyle == null)
						{
							rowStyle = new GridRowStyle();
						}
						object value = view.Row[this.SelectedRowCssClassDataField];
						if(value != null)
						{
							rowStyle.SelectedRowCssClass = value.ToString();
						}
					}
				}
				else
				{
					Type type = e.Item.DataItem.GetType();
					if (!string.IsNullOrEmpty(this.RowCssClassDataField))
					{
						PropertyInfo pi = type.GetProperty(this.RowCssClassDataField, BindingFlags.Public | BindingFlags.Instance);
						if (pi != null)
						{
							rowStyle = new GridRowStyle();
							object value = pi.GetValue(e.Item.DataItem, null);
							if(value != null)
							{
								rowStyle.RowCssClass = value.ToString();
							}
						}
					}
					if (!string.IsNullOrEmpty(this.SelectedRowCssClassDataField))
					{
						PropertyInfo pi = type.GetProperty(this.SelectedRowCssClassDataField, BindingFlags.Public | BindingFlags.Instance);
						if (pi != null)
						{
							if (rowStyle == null)
							{
								rowStyle = new GridRowStyle();
							}
							object value = pi.GetValue(e.Item.DataItem, null);
							if (value != null)
							{
								rowStyle.SelectedRowCssClass = value.ToString();
							}
						}
					}
				}
				if (rowStyle != null)
				{
					if (this._rowStyles == null)
					{
						this._rowStyles = new List<GridRowStyle>();
					}
					this._rowStyles.Insert(e.Item.DataSetIndex, rowStyle);
				}
            }
        }
    }

	public void Clear()
	{
		this._sortExpression = "";
		this.ViewState["SortExpression"] = _sortExpression;
		
		this._sortDirection = SortDirection.Ascending;
		this.ViewState["SortDirection"] = _sortDirection;
		
		this._pageNumber = 1;
		this.ViewState["PageNumber"] = _pageNumber;
		
		this._hasMorePages = false;
		this.ViewState["HasMorePages"] = _hasMorePages;
		
		this._pagingCookie = string.Empty;
		this._pagingCookie = (string)this.ViewState["PagingCookie"];

		this.SelectedIndices = null;
		this.hdnItemsExpanded.Value = string.Empty;

		for (int I = this.Columns.Count - 1; I > 0; I--)
		{
			this.Columns.RemoveAt(I);
		}

		this.innerGrid.DataSource = null;
		this.innerGrid.DataBind();
	}

	protected void firstPage_Click(object sender, ImageClickEventArgs e)
	{
		this._pageNumber = 1;
		DoQueryDataSource(QueryDataSourceReason.PageCommand);		
		
		this.ViewState["PageNumber"] = _pageNumber;
		this.lblPageInfo.Text = string.Format(this.PageInfoFormat, this._pageNumber);
	}
	
	protected void prevPage_Click(object sender, ImageClickEventArgs e)
	{
		this._pageNumber--;
		DoQueryDataSource(QueryDataSourceReason.PageCommand);

		this.ViewState["PageNumber"] = _pageNumber;
		this.lblPageInfo.Text = string.Format(this.PageInfoFormat, this._pageNumber);
		
	}
	
	protected void nextPage_Click(object sender, ImageClickEventArgs e)
	{
		this._pageNumber++;
		DoQueryDataSource(QueryDataSourceReason.PageCommand);

		this.ViewState["PageNumber"] = _pageNumber;
		this.lblPageInfo.Text = string.Format(this.PageInfoFormat, this._pageNumber);
		
	}

	public GridItemID[] SelectedItemIds
	{
		get
		{
			int[] selectedIndices = this.SelectedIndices;
			GridItemID[] itemIds = new GridItemID[selectedIndices.Length];
            for (int iCount = 0; iCount < selectedIndices.Length; iCount++)
            {
                itemIds[iCount] = _itemIds[selectedIndices[iCount]];
            }
			return itemIds;
		}
	}

    public int PageNumber
    {
        get
        {
            return _pageNumber;
        }
    }

    #region IPostBackEventHandler Members

    public void RaisePostBackEvent(string eventArgument)
    {
        if (eventArgument == "gridcontrol_refresh")
        {
            CancelEventArgs args = new CancelEventArgs();
            if (this.GridRefresh != null)
            {
                this.GridRefresh(this, args);
            }
            if (args.Cancel == false)
            {
                DoQueryDataSource(QueryDataSourceReason.DataBind);
            }
        }
    }

    #endregion
}

public enum QueryDataSourceReason
{
    DataBind,
    SortCommand,
    PageCommand
}

public class QueryDataSourceEventArgs : EventArgs
{
	private int _pageNumber = 1;
	private int _pageCount = 50;
	private bool _hasMorePages;
	private string _pagingCookie = string.Empty;
	private string _sortExpression = string.Empty;
    QueryDataSourceReason _reason;
    private bool _clearSelections = false;
	private SortDirection _sortDirection;

	public int PageNumber
	{
		get { return _pageNumber; }
		set { _pageNumber = value; }
	}

	public int PageCount
	{
		get { return _pageCount; }
		set { _pageCount = value; }
	}

	public string PagingCookie
	{
		get { return _pagingCookie; }
		set { _pagingCookie = value; }
	}

	public string SortExpression
	{
		get { return _sortExpression; }
		set { _sortExpression = value; }
	}

	public SortDirection SortDirection
	{
		get { return _sortDirection; }
		set { _sortDirection = value; }
	}

    public QueryDataSourceReason Reason
    {
        get { return _reason; }
        set { _reason = value; }
    }

    public bool ClearSelections
    {
        get { return _clearSelections; }
        set { _clearSelections = value; }
    }

	public bool HasMorePages
	{
		get { return _hasMorePages; }
		set { _hasMorePages = value; }
	}
}

public delegate void QueryDataSource(object sender, QueryDataSourceEventArgs args);
public delegate void GridRefresh(object sender, CancelEventArgs args);

[Serializable]
public class GridItemID
{
    private object id;
    private object code;
    private object label;

    public object ID
    {
        get { return id; }
        set { id = value; }
    }

    public object Code
    {
        get { return code; }
        set { code = value; }
    }

	public object Label
	{
		get { return label; }
		set { label = value; }
	}
}

[Serializable]
public class GridRowStyle
{
	//private int index = -1;
	private string rowCssClass = string.Empty;
	private string selectedRowCssClass = string.Empty;

	//public int Index
	//{
	//    get { return index; }
	//    set { index = value; }
	//}

	public string RowCssClass
	{
		get { return rowCssClass; }
		set { rowCssClass = value; }
	}

	public string SelectedRowCssClass
	{
		get { return selectedRowCssClass; }
		set { selectedRowCssClass = value; }
	}
}
